﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CarolLib.Configuration;
using System.Xml;


namespace CarolLib.WinService
{
    public class WinServiceConfiguration : ConfigurationBase
    {
        #region Properities

        public WinServiceSetting Settings { get; private set; }

        private Dictionary<string, TaskContainer<IBasicTask>> basicTasks = new Dictionary<string, TaskContainer<IBasicTask>>();

        public Dictionary<string, TaskContainer<IBasicTask>> BasicTasks
        {
            get { return basicTasks; }
        }

        #endregion

        #region Ctor.

        public WinServiceConfiguration()
            : base()
        { }

        public WinServiceConfiguration(XmlNode node)
            : base()
        {
            foreach (XmlNode child in node.ChildNodes)
            {
                switch (child.Name.ToLower())
                {
                    case "tasks":
                        this.LoadTasks<IBasicTask>(child, ref basicTasks, child);
                        break;
                }
            }
        }

        #endregion

        protected void LoadTasks<T>(XmlNode node, ref Dictionary<string,TaskContainer<T>> tasks, params object[] args)
            where T:ITask
        {
            if (tasks == null)
                tasks = new Dictionary<string, TaskContainer<T>>();

            if (node != null)
            {
                foreach (XmlNode n in node.ChildNodes)
                {
                    if (n.NodeType != XmlNodeType.Comment)
                    {
                        switch (n.Name)
                        {
                            case "clear":
                                tasks.Clear();
                                break;
                            case "remove":
                                XmlAttribute removeNameAtt = n.Attributes["name"];
                                string removeName = removeNameAtt == null ? null : removeNameAtt.Value;

                                if (!string.IsNullOrEmpty(removeName) && tasks.ContainsKey(removeName))
                                    tasks.Remove(removeName);

                                break;
                            case "add":
                                Log.Info("module: " + n.OuterXml);
                                XmlAttribute en = n.Attributes["enabled"];
                                if (en != null && en.Value == "false")
                                    continue;

                                XmlAttribute nameAtt = n.Attributes["name"];
                                XmlAttribute typeAtt = n.Attributes["type"];
                                XmlAttribute intvalAtt = n.Attributes["interval"];
                                string name = nameAtt == null ? null : nameAtt.Value;
                                string itype = typeAtt == null ? null : typeAtt.Value;
                                int intval = intvalAtt == null ? 10000 : int.Parse(intvalAtt.Value);

                                if (string.IsNullOrEmpty(name))
                                    continue;

                                if (string.IsNullOrEmpty(itype))
                                    continue;

                                Type type = Type.GetType(itype);

                                if (type == null)
                                    continue;

                                T mod = default(T);
                                TaskContainer<T> TC = new TaskContainer<T>(args);
                                
                                try
                                {
                                    mod = (T)Activator.CreateInstance(type);
                                    TC.Task = mod;
                                    TC.Interval = intval;
                                }
                                catch (Exception ex)
                                {
                                    Log.Exception(ex);
                                }

                                if (mod == null)
                                    continue;

                                tasks[name] = TC;
                                break;

                        }
                    }
                }
            }
        }

        public static WinServiceConfiguration GetConfig()
        {
            return GetConfig<WinServiceConfiguration>("serviceSetting");
        }

        protected override void LoadValuesFromConfigurationXml(System.Xml.XmlNode node)
        {
            Settings = new WinServiceSetting(node);
        }
    }
}
